package miku.firstgame.net
{
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.ObjectEncoding;
	import flash.net.Socket;
	import flash.system.Security;
	import flash.utils.ByteArray;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;

	import miku.firstgame.constrants.ProtocalConstants;
	import miku.firstgame.net.pack.IReceivePack;
	import miku.firstgame.net.pack.ISendPack;
	import miku.firstgame.net.pack.PingRequestPack;

	public class MikuSocketImpl extends Socket implements IConnection
	{
		protected var handler:IConnectionHandler;

		public static const REQUEST_TIMEOUT:int = 20 * 1000;
		public static const PING_INTERVAL_NUM:Number = 17000;

		private var pingIntervalID:int;
		private var timeoutId:int;

		private var cache:ByteArray;

		private var byteLength:int = 0;

		public function MikuSocketImpl()
		{
			//super(host, port);
			init();
		}

		override public function connect(host:String, port:int):void
		{
			Security.allowDomain("*");
			Security.loadPolicyFile("xmlsocket://" + host + ":" + port);
			super.connect(host, port);
		}

		protected function init():void
		{
			this.objectEncoding = ObjectEncoding.AMF3;

			cache = new ByteArray();

			//packet = new ByteArray();
			addEventListener(ProgressEvent.SOCKET_DATA, onData);
			addEventListener(Event.CONNECT, onConnect);
			addEventListener(Event.CLOSE, onClose);
			addEventListener(IOErrorEvent.IO_ERROR, onError);
			addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
		}

		protected function onData(event:ProgressEvent):void
		{
			trace("======接收到数据段,数据段有效长度: " + this.bytesAvailable);
			while (bytesAvailable > 0)
			{
				if (byteLength == 0 && bytesAvailable <= 4)
				{
					trace("读取数据失败：长度    bytesAvailable <= 4");
					return;
				}

				//this.readBytes(cache, 0, bytesAvailable);
				if (byteLength == 0)
				{
					byteLength = readUnsignedInt();
					trace("当前包长度：" + byteLength);
				}
				cache.position = 0;
				if ((bytesAvailable + cache.bytesAvailable) >= byteLength)
				{
					var pack:ByteArrayEx = new ByteArrayEx();

					var cacheLength:int = cache.bytesAvailable;

					if (cacheLength == 0)
					{
						readBytes(pack, 0, byteLength);
					}
					else
					{
						cache.readBytes(pack, 0, cacheLength);
						readBytes(pack, cacheLength, byteLength - cacheLength);
						cache.clear();
					}
					//TODO 考虑解密

					var tag:int = pack.readUnsignedShort();
					var package1:IReceivePack = ProtocalConstants.getReceivePack(tag, pack); //已经decode好的
					byteLength = 0;
					handler.handleData(package1, this);
				}
				else
				{
					readBytes(cache, cache.length, bytesAvailable);
				}

//				if (len == 0)
//				{
//					len = readUnsignedInt(); //读取流的长度
//					Logger.info("this is len ======" + len);
//					packByte.writeUnsignedInt(len);
//					len -= 4;
//				}
//				Logger.info("Protocol Len = " + (len + 4));
					//可读数据长度如果大于等于服务器传过来的长度，则读取服务器当前包长度的数据
//				if (bytesAvailable >= len)
//				{
//					readBytes(packByte, 4, len);
//
//					packByte.position = 4;
//					var cmd:int = packByte.readUnsignedInt();
//					if (cmd == 1016)
//					{
//						var pwd:String = MD5.hash(Me.instance.pwd);
//						XXTea.init(pwd);
//					}
//					Logger.info('Receive cmd=====' + cmd);
//					unescape(packByte);
//					if (endFlagDic[cmd])
//					{
//						packByte.position = 28;
//						var ret:uint = packByte.readUnsignedInt();
//						if (ret != 0)
//						{
//							Logger.error('SocketImpl ret :::::::::::::::::::::::::::::::' + ret);
//							clearProtocolDic();
//							packs = new Vector.<MByteArray>();
//							return;
//						}
//						packByte.position = endFlagDic[cmd] as int;
//						var endFlag:int = packByte.readUnsignedInt();
//						Logger.info("tnum==" + packByte.readUnsignedInt() + "   num==" + packByte.readUnsignedInt());
//						Logger.info('Receive endFlag=====' + endFlag);
//						var cellPack:MByteArray = new MByteArray(true);
//						packByte.position = 0;
//						packByte.readBytes(cellPack);
//						Logger.info("SocketImpl cellPack: " + Hex.fromArray(cellPack));
//						packs.push(cellPack);
//						if (endFlag == 1)
//						{
//							dispatchEvent(new SocketEvent(SocketEvent.IMO_RECEIVE_MULTI_DATA, packs));
//							clearProtocolDic();
//							packs = new Vector.<MByteArray>();
//						}
//						else
//						{
//							len = 0;
//						}
//					}
//					else
//					{
//						dispatchEvent(new SocketEvent(SocketEvent.IMO_RECEIVE_DATA, packByte));
//						clearProtocolDic();
//					}
//
//					packByte.clear();
//
//				}
//				else
//				{
//					Logger.show("读取数据失败：长度 bytesAvailable < len" + "bytesAvailable==" + bytesAvailable + "len===" + len);
//					return;
//				}
			}
		}

		public function send(data:Object):void
		{
			if (data is ISendPack)
			{
				writeBytes((data as ISendPack).encode());
				flush();
			}
			else
			{
				trace("发送数据格式不正确:" + data);
			}
		}

		private function onClose(event:Event):void
		{
			handler.handleClose(this);
			clearInterval(pingIntervalID);
		}

		private function onConnect(event:Event):void
		{
			handler.handleConnect(this);
			ping();
		}

		private function onError(event:Event):void
		{
			trace("Connection error: " + event["text"]);
			handler.handleError(this);
		}

		public function ping(pingFunction:Function = null):void
		{
			var connection:IConnection = this;
			clearInterval(pingIntervalID);
			if (null == pingFunction)
			{
				pingIntervalID = setInterval(function():void
				{
					if (this.connected) //WrappedSock.isLoadInitProtocol)
					{
						connection.send(new PingRequestPack());
					}

				}, PING_INTERVAL_NUM);
			}
			else
			{
				pingIntervalID = setInterval(pingFunction, PING_INTERVAL_NUM);
			}
		}

		public function setHandler(handler:IConnectionHandler):void
		{
			this.handler = handler;
		}
	}
}
